package cn.gzsf.csmall.product.ex.Handler;


import cn.gzsf.csmall.product.web.JsonResult;
import cn.gzsf.csmall.product.ex.ServiceException;
import cn.gzsf.csmall.product.web.ServiceCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

import java.util.Set;

@Slf4j
@RestControllerAdvice//加此注解，标志此类为全局异常处理类
public class GlobalExceptionHandler {

    @ExceptionHandler
    public JsonResult handleServiceException(ServiceException e){
        log.warn("程序运行过程中出现了ServiceException，将统一处理");
        log.warn("异常信息:{}",e.getMessage());
        return JsonResult.fail(e.getServiceCode(), e.getMessage());
    }

    @ExceptionHandler
    public JsonResult handleConstraintViolationException(ConstraintViolationException e){
        log.warn("程序运行过程中出现了ConstraintViolationException，将统一处理");
        log.warn("异常信息:{}",e.getMessage());
        //取出错误信息，下面的代码不要掌握，
        String message = null;
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        for(ConstraintViolation<?> constraintViolation:constraintViolations){
            message = constraintViolation.getMessage();
        }

      /*  JsonResult jsonResult = new JsonResult();
        jsonResult.setState(3);
        jsonResult.setMessage(message);*/

        return JsonResult.fail(ServiceCode.ERR_BAD_REQUEST, message);
    }

    @ExceptionHandler
    public JsonResult handleBindException(BindException e){
        log.warn("程序运行过程中出现了BindException，将统一处理");
        log.warn("异常信息:{}",e.getMessage());
        log.warn("BindException异常",e);
        //【解决方案-1】使用一个字符串表示一个错误
        String message = e.getFieldError().getDefaultMessage();


        return JsonResult.fail(ServiceCode.ERR_BAD_REQUEST,message);
        //【解决方案-2】使用一个字符串表示错误信息
       // StringBuilder stringBuilder = new StringBuilder();//字符串生成器，用于字符串拼接
      /*  StringJoiner stringBuilder = new StringJoiner(", ","请求参数错误,","!");
        List<FieldError> fieldErrors = e.getFieldErrors();//获取所有属性校验错误
        for(FieldError fieldError:fieldErrors){//遍历
            String defaultMessage = fieldError.getDefaultMessage();//获取每个错误信息
            stringBuilder.add(defaultMessage);//拼接错误信息
        }*/
        //【解决方案-3】使用集合表示多个错误信息，需要将当前方法的返回值类型声明为对应的集合类型
     /*   List<String> list = new ArrayList<>();
        List<FieldError> fieldErrors = e.getFieldErrors();//获取所有属性校验错误
        for(FieldError fieldError:fieldErrors) {//遍历
            String defaultMessage = fieldError.getDefaultMessage();//获取每个错误信息
            list.add(defaultMessage);//拼接错误信息
        }*/

    }

    @ExceptionHandler
    public JsonResult handleServiceException(Throwable e){
        log.warn("程序运行过程中出现了未知Throwable，将统一处理");
        log.warn("异常信息:{}",e.getMessage());
        log.warn("异常",e);//取代e.printStackTrace();效果相同，注意第一个参数中不要用{}进行占位
        String message = "服务器忙，请稍后再试!【如果在开发过程中，看到此提示，应检测服务器控制台，" +
                "分析异常，并在全局异常处理类中补充处理应对这个异常的方法】";

       /* JsonResult jsonResult = new JsonResult();
        jsonResult.setState(9999);
        jsonResult.setMessage(message);
*/
        return JsonResult.fail(ServiceCode.ERR_UNKNOWN,message);
    }

}
